package com.example.gui;

import javax.script.*;
import javax.swing.*;  
import java.awt.*;  
import java.awt.event.ActionEvent;  
import java.awt.event.ActionListener;  

public class SwingJSExecutor {  
    private JFrame frame;  
    private JTextField jsInput;  
    private JTextArea resultArea;  

    public SwingJSExecutor() {  
        // 初始化界面  
        initUI();  
    }  

    // 初始化Swing界面  
    private void initUI() {  
        frame = new JFrame("Java Swing执行JavaScript");  
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
        frame.setSize(600, 400);  
        frame.setLayout(new BorderLayout(10, 10)); // 边框布局，组件间距10px  

        // 1. 顶部输入区域（标签+输入框+按钮）  
        JPanel inputPanel = new JPanel(new BorderLayout(5, 5));  
        inputPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10)); // 外边框留白  

        JLabel label = new JLabel("输入JavaScript代码：");  
        jsInput = new JTextField("console.log('Hello JS!'); 1+2*3;"); // 默认示例代码  
        JButton executeBtn = new JButton("执行");  

        inputPanel.add(label, BorderLayout.WEST);  
        inputPanel.add(jsInput, BorderLayout.CENTER);  
        inputPanel.add(executeBtn, BorderLayout.EAST);  

        // 2. 中部结果显示区域  
        resultArea = new JTextArea();  
        resultArea.setEditable(false); // 结果区域不可编辑  
        resultArea.setLineWrap(true); // 自动换行  
        JScrollPane scrollPane = new JScrollPane(resultArea); // 滚动面板包裹文本区域  
        scrollPane.setBorder(BorderFactory.createTitledBorder("执行结果"));  

        // 3. 添加组件到窗口  
        frame.add(inputPanel, BorderLayout.NORTH);  
        frame.add(scrollPane, BorderLayout.CENTER);  

        // 4. 绑定按钮点击事件  
        executeBtn.addActionListener(new ActionListener() {  
            @Override  
            public void actionPerformed(ActionEvent e) {  
                executeJSCode(); // 点击按钮时执行JS代码  
            }  
        });  

        frame.setVisible(true); // 显示窗口  
    }  

    // 核心方法：执行JS代码并显示结果  
    private void executeJSCode() {  
        // 1. 获取JDK内置的JavaScript引擎  
        ScriptEngineManager engineManager = new ScriptEngineManager();  
        ScriptEngine jsEngine = engineManager.getEngineByName("JavaScript"); // 或简写"js"  

        if (jsEngine == null) {  
            resultArea.append("错误：未找到JavaScript引擎（请使用JDK 8+）\n");  
            return;  
        }  

        // 2. 重定向JS的console.log到Java界面（自定义输出）  
        try {  
            // 创建绑定对象，将Java的输出方法注入JS环境  
            Bindings bindings = jsEngine.getBindings(ScriptContext.ENGINE_SCOPE);  
            bindings.put("log", new LogHandler(resultArea)); // 注入log方法到JS  

            // 3. 替换JS的console.log为自定义log方法  
            jsEngine.eval("var console = { log: function(msg) { log.print(msg); } };");  
        } catch (ScriptException e) {  
            resultArea.append("初始化错误：" + e.getMessage() + "\n");  
            return;  
        }  

        // 4. 获取用户输入的JS代码并执行  
        String jsCode = jsInput.getText().trim();  
        resultArea.append("------------------------\n执行代码：" + jsCode + "\n");  

        try {  
            // 执行JS代码并获取返回值  
            Object result = jsEngine.eval(jsCode);  

            // 5. 显示执行结果  
            if (result != null) {  
                resultArea.append("返回结果：" + result + "\n");  
            } else {  
                resultArea.append("执行完成（无返回值）\n");  
            }  
        } catch (ScriptException e) {  
            // 捕获JS语法错误或运行时异常  
            resultArea.append("执行错误：" + e.getMessage() + "\n");  
        }  
    }  

    // 自定义日志处理器：将JS输出重定向到Swing文本区域  
    static class LogHandler {  
        private JTextArea textArea;  

        public LogHandler(JTextArea textArea) {  
            this.textArea = textArea;  
        }  

        // JS中调用log.print(msg)时，会执行此方法  
        public void print(Object message) {  
            textArea.append("JS输出：" + message + "\n");  
        }  
    }  

    // 主方法：启动程序  
    public static void main(String[] args) {  
        // Swing组件需在事件调度线程中创建（避免线程安全问题）  
        SwingUtilities.invokeLater(new Runnable() {  
            @Override  
            public void run() {  
                new SwingJSExecutor();  
            }  
        });  
    }  
}